﻿using System.Linq;
using IGS.Core.Integrators;
using IGS.Core.Systems;
using Moq;
using NUnit.Framework;

namespace IGS.Core.Tests.Integrators
{
    public static class BaseIntegratorTests
    {
        [TestFixture]
        public class GivenAnNBodySystem
        {
            [Test]
            public void WhenPredictIsCalledThenPredictShouldBeCalledOnAllBodies()
            {
                // Arrange
                var system = new Mock<INBodySystem>();
                var bodies = new[]
                {
                    new Mock<IInteractable>().Object,
                    new Mock<IInteractable>().Object
                };
                system.Setup(s => s.GetEnumerator()).Returns(bodies.AsEnumerable().GetEnumerator());
                const double dt = 0.01;
                var integrator = new Mock<BaseIntegrator>();

                // Act
                integrator.Object.Predict(system.Object, dt);

                // Assert
                foreach (var body in bodies)
                {
                    var b = body;
                    integrator.Verify(i => i.Predict(b, dt));
                }
            }

            [Test]
            public void WhenCorrectIsCalledThenCorrectShouldBeCalledOnAllBodies()
            {
                // Arrange
                var system = new Mock<INBodySystem>();
                var bodies = new[]
                {
                    new Mock<IInteractable>().Object,
                    new Mock<IInteractable>().Object
                };
                system.Setup(s => s.GetEnumerator()).Returns(bodies.AsEnumerable().GetEnumerator());
                const double dt = 0.01;
                var integrator = new Mock<BaseIntegrator>();

                // Act
                integrator.Object.Correct(system.Object, dt);

                // Assert
                foreach (var body in bodies)
                {
                    var b = body;
                    integrator.Verify(i => i.Correct(b, dt));
                }
            }
        }
    }
}
